#include <stdlib.h>
#include <time.h>
#include "ToolManager.h"
#include "include.h"
#include "GL/glut.h"
#include "LevelReader.h"
#include "TextBox.h"
#include "InputElement.h"
#include "FormMenu.h"

#define TIME_BETWEEN_POSITIONS 5000.0/(double)CLOCKS_PER_SEC

ToolManager::ToolManager()
{
	leftClickDepressed = false;
	leftClickWasDepressed = false;
	saveKeyDepressed = false;
	saveKeyWasDepressed = false;
	rightClickDepressed = false;
	rightClickWasDepressed = false;
	toolCycleKeyDepressed = false;
	toolCycleKeyWasDepressed = false;
	toolBackwardCycleKeyDepressed = false;
	toolBackwardCycleKeyWasDepressed = false;
	toolNextModeKeyDepressed = false;
	toolNextModeKeyWasDepressed = false;
	toolLastModeKeyDepressed = false;
	toolLastModeKeyWasDepressed = false;
	zoomInKeyDepressed = false;
	zoomInKeyWasDepressed = false;
	zoomOutKeyDepressed = false;
	zoomOutKeyWasDepressed = false;
	
	exit = false;
	camera = new Camera(&mouse);
	mouse.SetCamera(camera);
	lastThoughtTimestamp = (float)clock()/CLOCKS_PER_SEC;
	materialList= NULL;
	textureManager = new TextureManager();
	tool = new Tool(textureManager, &mouse, materialList);
	
	VertexList * vertices = new VertexList(new Vertex(Vector2D(-10,-20)));
	vertices->Add(new Vertex(Vector2D(10,-20)));
	Border * newBorder = new Border(vertices);
	objectList = new ObjectList(newBorder);
	fileName = "newLevel.lvl";
}
ToolManager::ToolManager(char * filename)
{
	printf("trying\n");
	this->fileName = filename;
	leftClickDepressed = false;
	leftClickWasDepressed = false;
	rightClickDepressed = false;
	rightClickWasDepressed = false;
	saveKeyDepressed = false;
	saveKeyWasDepressed = false;
	toolCycleKeyDepressed = false;
	toolCycleKeyWasDepressed = false;
	toolBackwardCycleKeyDepressed = false;
	toolBackwardCycleKeyWasDepressed = false;
	toolNextModeKeyDepressed = false;
	toolNextModeKeyWasDepressed = false;
	toolLastModeKeyDepressed = false;
	toolLastModeKeyWasDepressed = false;
	toolNextParameterKeyDepressed = false;
	toolNextParameterKeyWasDepressed = false;
	toolLastParameterKeyDepressed = false;
	toolLastParameterKeyWasDepressed = false;
	exit = false;
	camera = new Camera(&mouse);
	mouse.SetCamera(camera);
	lastThoughtTimestamp = (float)clock()/CLOCKS_PER_SEC;
	
	//Border * border = NULL;
	printf("loading\n");
	textureManager = new TextureManager();
	CreateGui();
	objectList = new ObjectList(menuManager);
	LevelReader::LoadLevel(textureManager, &objectList, &materialList, fileName);
	tool = new Tool(textureManager, &mouse, materialList);
	printf("Created!\n");
	/*if(!border)
	{
		VertexList * vertices = new VertexList(new Vertex(Vector2D(-10,-20)));
		vertices->Add(new Vertex(Vector2D(10,-20)));
		border = new Border(vertices);
	}
	objectList = new ObjectList(border);*/
	
	
	
}
ToolManager::~ToolManager()
{
	if(camera)
	{	
		delete camera;
		camera = NULL;
	}
	if(tool)
	{
		delete tool;
		tool = NULL;
	}
	if(objectList)
	{
		delete objectList;
		objectList = NULL;
	}
	if(materialList)
	{
		delete materialList;
		materialList = NULL;
	}
	if(menuManager)
	{
		delete menuManager;
		menuManager = NULL;
	}
	if(textureManager)
	{
		delete textureManager;
		textureManager = NULL;
	}
}
void ToolManager::CreateGui()
{
	currentParameterText = new TextBox(textureManager, "", Vector2D(0.5,7), Vector2D(17,5), 1.5);
	currentToolText = new TextBox(textureManager, "Edit", Vector2D(0.5,0.5), Vector2D(17,5), 1.5);
	currentModeText = new TextBox(textureManager, "Vertex", Vector2D(0.5,3.5), Vector2D(17,5),1.5);
	//InputElement * inputElement = new InputElement(textureManager, Vector2D(0.5, 9), 1.5, 20);
	MenuElementList * list = new MenuElementList(currentToolText);
	list->Add(currentModeText);
	list->Add(currentParameterText);
	//list->Add(inputElement);
	Menu * guiMenu = new Menu(list, Vector2D(0,0),0);
	menuManager = new MenuManager(guiMenu);
		
}
void ToolManager::PrepareFrame()
{
	//printf("ToolManager::PrepareFrame\n");
	float currentTime = (float)clock()/(float)CLOCKS_PER_SEC;
	float elapsedTime = currentTime - lastThoughtTimestamp;

	if(elapsedTime >= TIME_BETWEEN_POSITIONS)
	{
		lastThoughtTimestamp = currentTime;	
	}
	else
	{
		return;
	}
	
	for(;elapsedTime >= TIME_BETWEEN_POSITIONS; elapsedTime -= TIME_BETWEEN_POSITIONS)
	{
		float thisTime = TIME_BETWEEN_POSITIONS;
		if(elapsedTime < TIME_BETWEEN_POSITIONS)
			thisTime = elapsedTime; 
	
		thisTime /= 2.0;

		HandleUserInput();
		camera->Think(thisTime);
		tool->Think(thisTime);
		mouse.Think();
	}
	//printf("ToolManager::PrepareFrame Done\n");
}
void ToolManager::Draw()
{
	//printf("ToolManager::Draw\n");
	if(menuManager)
		menuManager->Draw();
	camera->Draw();
	if(objectList)
		objectList->Draw();
	glPushMatrix();
	glLoadIdentity();
	
	glColor3f(1,1,1);
	
	glBegin(GL_LINES);
	glVertex2f(0,10);
	glVertex2f(0,-10);
	glVertex2f(-10,0);
	glVertex2f(10,0);
	glEnd();
	
	glPopMatrix();	
	//printf("ToolManager::Draw Done\n");
}
void ToolManager::SetNormalUserInput(unsigned char key, int modifier, bool isDepressed)
{
	printf("key =%d\n",key);
	if(!menuManager->HandleUserInput(key, modifier, isDepressed))
	{
		if(modifier == GLUT_ACTIVE_CTRL)
		{
			printf("Active ctrl\n");
			switch(key)
			{
				case 9: toolBackwardCycleKeyDepressed = isDepressed;break;
				case 19:  saveKeyDepressed = isDepressed;break;
			}	
		}
		else
		{
			
			switch(key)
			{
				case 45: zoomOutKeyDepressed = isDepressed;break;
				case 61: zoomInKeyDepressed = isDepressed;break;
				case 9: toolCycleKeyDepressed = isDepressed;break;
			}	
		}
	}
}
void ToolManager::SetUserInput(int key, int modifier, bool isDepressed)
{
	switch(key)
	{
		case GLUT_KEY_LEFT: toolLastModeKeyDepressed = isDepressed; break;
		case GLUT_KEY_RIGHT: toolNextModeKeyDepressed = isDepressed; break;
		case GLUT_KEY_UP: toolNextParameterKeyDepressed = isDepressed; break;
		case GLUT_KEY_DOWN: toolLastParameterKeyDepressed = isDepressed; break;
	}
}
void ToolManager::SetUserInput(int key, bool isDepressed, float x, float y)
{
	switch(key)
	{
		case GLUT_RIGHT_BUTTON: rightClickDepressed = isDepressed; break;
		case GLUT_LEFT_BUTTON: leftClickDepressed = isDepressed; break;
	}
}
void ToolManager::SetPassiveMouse(float x, float y)
{
	mouse.SetPosition(x,y, camera->GetSize());
}	
void ToolManager::SetActiveMouse(float x, float y)
{
	mouse.SetPosition(x,y, camera->GetSize());
}

void ToolManager::HandleUserInput()
{
	//printf("ToolManager::HandleUserInput\n");
	if(zoomInKeyDepressed)
	{
		if(camera)
		{
			camera->ZoomIn();
		}
	}
	if(zoomOutKeyDepressed)
	{
		if(camera)
		{
			camera->ZoomOut();
		}
	}
	if(toolNextParameterKeyDepressed && !toolNextParameterKeyWasDepressed)
	{
		if(tool)
		{
			tool->NextParameter();
			currentParameterText->SetText(tool->GetParameterName());
		}
	}
	if(toolLastParameterKeyDepressed && !toolLastParameterKeyWasDepressed)
	{
		if(tool)
		{
			tool->LastParameter();
			currentParameterText->SetText(tool->GetParameterName());
		}
	}
	if(toolNextModeKeyDepressed && !toolNextModeKeyWasDepressed)
	{
		if(tool)
		{
			tool->NextMode();
			currentModeText->SetText(tool->GetModeName());
			currentParameterText->SetText(tool->GetParameterName());
		}
	}
	if(toolLastModeKeyDepressed && !toolLastModeKeyWasDepressed)
	{
		if(tool)
		{
			tool->LastMode();
			currentModeText->SetText(tool->GetModeName());
			currentParameterText->SetText(tool->GetParameterName());
		}
	}
	if(toolCycleKeyDepressed && !toolCycleKeyWasDepressed)
	{
		if(tool)
		{
			tool->NextTool();
			SetCurrentToolText();
		}
	}
	if(toolBackwardCycleKeyDepressed && !toolBackwardCycleKeyWasDepressed)
	{
		if(tool)
		{
			tool->LastTool();
			SetCurrentToolText();
		}
	}
	if(rightClickDepressed && !rightClickWasDepressed)
	{
		if(tool)
		{
			tool->SecondaryFunction();
		}
	}
	if(leftClickDepressed && !leftClickWasDepressed)
	{
		Vector2D mPoint = mouse.GetPosition();
		mPoint.x = (mPoint.x + 100)/2.0;
		mPoint.y = (mPoint.y + 100)/2.0;
		//printf("Y COORD = %f\n", mPoint.y);
		if(!menuManager->Click(mPoint))
		{
			if(tool)
			{
				//tool->PrimaryFunction(border);
				tool->PrimaryFunction(objectList);
			}	
		}
	}
	if(!leftClickDepressed && leftClickWasDepressed)
	{
		if(tool)
		{
			//tool->LiftPrimaryFunction(border);
			tool->LiftPrimaryFunction();
		}
	}
	if(saveKeyDepressed && !saveKeyWasDepressed)
	{
		SaveLevel();	
	}
	
	if(tool->GetCurrentToolId() == EDIT_TOOL_ID)
	{
		if(tool->HasSelectedObject())
			tool->CheckSelectedObjectHover();
		else
			objectList->HoverCheck(&mouse);
	}
	
	toolCycleKeyWasDepressed = toolCycleKeyDepressed;
	toolBackwardCycleKeyWasDepressed = toolBackwardCycleKeyDepressed;
	leftClickWasDepressed = leftClickDepressed;
	rightClickWasDepressed = rightClickDepressed;
	saveKeyWasDepressed = saveKeyDepressed;
	toolNextModeKeyWasDepressed = toolNextModeKeyDepressed;
	toolLastModeKeyWasDepressed = toolLastModeKeyDepressed;
	toolNextParameterKeyWasDepressed = toolNextParameterKeyDepressed;
	toolLastParameterKeyWasDepressed = toolLastParameterKeyDepressed;
	zoomInKeyWasDepressed = zoomInKeyDepressed;
	zoomOutKeyWasDepressed = zoomOutKeyDepressed;
	//printf("ToolManager::HandleUserInput Done\n");
}
void ToolManager::SetCurrentToolText()
{
	switch(tool->GetCurrentToolId())
	{
		case EDIT_TEXTURE_ID:
			currentToolText->SetText("Texture");
		break;
		case EDIT_TOOL_ID:
			currentToolText->SetText("Edit");
		break;
		case CREATE_OBJECT_TOOL_ID:
			currentToolText->SetText("Create");
		break;
	}
	currentModeText->SetText(tool->GetModeName());
	currentParameterText->SetText(tool->GetParameterName());
}
Vector2D ToolManager::GetCameraSize()
{
	if(camera)
	{
		return camera->GetSize();
	}
	return Vector2D(0,0);
}

void ToolManager::SaveLevel()
{
	printf("Saving\n");
	char * tag = objectList->GetTags();
	
	printf("Tag = %s\n", tag);
	FILE * fptr = NULL;

	if((fptr = fopen(fileName, "w")) == NULL)
	{
		printf("Error opening level -%s-\n", fileName);
	}
	else
	{
		fprintf(fptr, "<background,./Images/summersky2.bmp, 2,./Images/mountainparallax.bmp,(0.002, 0.0),(0.75, 0.3652),(0,0.19),(1,0.6),(0,0.0),./Images/mountainparallax.bmp,(0.00015, 0.0),(0.75, 0.15332),(0,0.0),(1,0.5),(0,0.1)>\n");
		fprintf(fptr, "<player,(0,0)>\n");
		fprintf(fptr, "<material, boulder, ./Images/boulder.bmp, 0, 1000, 1, 0.1>\n");
		fprintf(fptr, "<material, log, ./Images/log.bmp, 0, 500, 1, 0.1>\n");
		fprintf(fptr, "<material, stonewall, ./Images/stonewall.bmp, 0, 1000, 1, 0.01>\n");
		fprintf(fptr, "<material, wood, ./Images/wood.bmp, 0, 200, 2, 0.1>\n");
		fprintf(fptr, "%s\n",tag);
		printf("Done writing tag\n");
		fclose(fptr);
		fptr=NULL;
	}
	
}
